package web

import (
	"fmt"
	"github.com/gookit/validate"
	"github.com/mojocn/base64Captcha"
	"ksd-social-api/commons/base/controller"
	"ksd-social-api/modules/common/sms/contants"
	"ksd-social-api/modules/common/sms/context"
	"ksd-social-api/modules/common/sms/service"
	uservice "ksd-social-api/modules/user/service"
	"ksd-social-api/utils/rdb"
)

type SMSController struct {
	controller.BaseController
}

var smsService = service.SMSService{}
var userService = uservice.UserService{}

// 用于验证码验证的时候使用
var store = base64Captcha.DefaultMemStore
var driver = base64Captcha.DefaultDriverDigit

/**
 * @author feige
 * @date 2023-10-09
 * @version 1.0
 * @desc  注册发短信
 */
func (web *SMSController) SendPhoneCodeReg() {
	// 1: 准备一个参数容器
	phoneContext := context.SMSPhoneContext{}
	// 2: 绑定参数
	web.BindJSON(&phoneContext)
	// 3: 对登录用户信息进行验证
	validation := validate.Struct(phoneContext)
	if !validation.Validate() {
		web.FailWithValidatorData(validation)
		return
	}

	// 判断用户是否绑定手机，如果已经绑定了就直接返回
	uvo := userService.GetUserById(web.GetUserId(), web.GetSystemId())
	if len(uvo.Telephone) > 0 {
		web.FailCodeMsg(607, "此账号已绑定手机！")
		return
	}

	//4： 验证码的校验
	captcha := base64Captcha.NewCaptcha(driver, store)
	// 参数1：是验证码key, 参数2 是验证码明文 参数3：true代表只要验签过参数1的key就立即失效。前端一般要重新生成一个id和验证码
	verify := captcha.Verify(phoneContext.CaptchaId, phoneContext.Vcode, true)
	if !verify {
		// 输入的验证码有误
		web.FailCodeMsg(602, "你输入的验证码有误！")
		return
	}

	// 判断你的手机是否被使用过了，如果使用过也直接返回
	phoneContext.SystemId = web.GetSystemId()
	userVo := userService.GetUserInfoByTelephone(phoneContext.Telephone, web.GetSystemId())
	if userVo != nil {
		web.FailCodeMsg(603, "你的手机已被使用！")
		return
	}

	// 5: 使用redis缓存进行数据共享
	// PHONE:SMS:24:15000000000  100054
	cacheKey := fmt.Sprintf(contants.SMS_PHONE_KEY+"%d:%s:%d", web.GetUserId(), phoneContext.Telephone, web.GetSystemId())
	// 让用户在4分钟以内，只能发送一次
	cacheCode, _ := rdb.RdbGet(cacheKey)
	if len(cacheCode) > 0 {
		web.FailCodeMsg(contants.SMS_PHONE_STATUS, contants.SMS_PHONE_LIMIT_TIME)
		return
	}

	// 4: 根据手机号码发送短信的接口
	sendCode, flag, err := smsService.SendPhone(phoneContext.Telephone)
	if flag {
		// 6: 丢入缓存中
		rdb.RdbSetEX(cacheKey, sendCode, contants.SMS_PHONE_LIMIT_SECONDS)
		// 7: 返回发送是否成功
		web.Ok(sendCode)
	} else {
		web.FailData(err)
	}
}

/**
 * @author feige
 * @date 2023-10-09
 * @version 1.0
 * @desc  登录发送
 */
func (web *SMSController) SendPhoneCodeLogin() {
	// 1: 准备一个参数容器
	phoneContext := context.SMSPhoneContext{}
	// 2: 绑定参数
	web.BindJSON(&phoneContext)
	// 3: 对登录用户信息进行验证
	validation := validate.Struct(phoneContext)
	if !validation.Validate() {
		web.FailWithValidatorData(validation)
		return
	}

	//4： 验证码的校验
	captcha := base64Captcha.NewCaptcha(driver, store)
	// 参数1：是验证码key, 参数2 是验证码明文 参数3：true代表只要验签过参数1的key就立即失效。前端一般要重新生成一个id和验证码
	verify := captcha.Verify(phoneContext.CaptchaId, phoneContext.Vcode, true)
	if !verify {
		// 输入的验证码有误
		web.FailCodeMsg(602, "你输入的验证码有误！")
		return
	}

	// 5: 使用redis缓存进行数据共享
	cacheKey := fmt.Sprintf(contants.SMS_PHONE_KEY+"%d:%s", web.GetSystemId(), web.GetIpAddr())
	cacheCode, _ := rdb.RdbGet(cacheKey)
	if len(cacheCode) > 0 {
		web.FailCodeMsg(contants.SMS_PHONE_STATUS, contants.SMS_PHONE_LIMIT_TIME)
		return
	}
	// 4: 根据手机号码发送短信的接口
	sendCode, flag, err := smsService.SendPhone(phoneContext.Telephone)
	if flag {
		// 6: 丢入缓存中
		rdb.RdbSetEX(cacheKey, sendCode, contants.SMS_PHONE_LIMIT_SECONDS)
		// 7: 返回发送是否成功
		web.Ok(sendCode)
	} else {
		web.FailData(err)
	}
}

/**
 * @author feige
 * @date 2023-10-09
 * @version 1.0
 * @desc  找回密码发送短信
 */
func (web *SMSController) SendPhoneCodeForget() {
	// 1: 准备一个参数容器
	phoneContext := context.SMSPhoneContext{}
	// 2: 绑定参数
	web.BindJSON(&phoneContext)
	// 3: 对登录用户信息进行验证
	validation := validate.Struct(phoneContext)
	if !validation.Validate() {
		web.FailWithValidatorData(validation)
		return
	}
	//4： 验证码的校验
	captcha := base64Captcha.NewCaptcha(driver, store)
	// 参数1：是验证码key, 参数2 是验证码明文 参数3：true代表只要验签过参数1的key就立即失效。前端一般要重新生成一个id和验证码
	verify := captcha.Verify(phoneContext.CaptchaId, phoneContext.Vcode, true)
	if !verify {
		// 输入的验证码有误
		web.FailCodeMsg(602, "你输入的验证码有误！")
		return
	}

	// 手机号码
	userVo := userService.GetUserInfoByTelephone(phoneContext.Telephone, web.GetSystemId())
	if userVo == nil {
		web.FailCodeMsg(603, "查无此手机号码，点击前往注册！")
		return
	}

	// 5: 使用redis缓存进行数据共享
	cacheKey := fmt.Sprintf(contants.SMS_PHONE_KEY+"%s:%d:%s", phoneContext.Telephone, web.GetSystemId(), web.GetIpAddr())
	cacheCode, _ := rdb.RdbGet(cacheKey)
	if len(cacheCode) > 0 {
		web.FailCodeMsg(contants.SMS_PHONE_STATUS, contants.SMS_PHONE_LIMIT_TIME)
		return
	}
	// 4: 根据手机号码发送短信的接口
	sendCode, flag, err := smsService.SendPhone(phoneContext.Telephone)
	if flag {
		// 6: 丢入缓存中
		rdb.RdbSetEX(cacheKey, sendCode, contants.SMS_PHONE_LIMIT_SECONDS)
		// 7: 返回发送是否成功
		web.Ok(sendCode)
	} else {
		web.FailData(err)
	}
}
